package user

import (
	"net/http"
	"strings"
	"time"

	"github.com/google/uuid"
	"github.com/labstack/echo/v4"
	"github.com/rs/zerolog/log"
	"techoiceness.com/aiagent/llm-gateway/internal/entity"
	"techoiceness.com/aiagent/llm-gateway/internal/server/response"
	"techoiceness.com/aiagent/llm-gateway/internal/server/sse"
)

// Chat processes a chat request and returns a response.
func (h *UserHandler) Chat(c echo.Context) error {
	var req ChatRequest
	if err := c.Bind(&req); err != nil {
		return response.BadRequest(c, "Invalid request")
	}

	// 验证请求参数
	if err := h.validator.Struct(&req); err != nil {
		return response.BadRequest(c, "Validation failed: "+err.Error())
	}

	// 解析 conversationID 为 UUID
	conversationUUID, err := uuid.Parse(req.ConversationID)
	if err != nil {
		return response.BadRequest(c, "Invalid conversation ID format")
	}

	var userMessage *entity.ClientMessage
	var assistantMessage *entity.ClientMessage

	// 在处理开始时就生成对话轮次ID
	conversationRoundID := uuid.New()

	// 检查用户认证并创建用户消息记录
	if user := c.Get("account"); user != nil {
		if u, ok := user.(*entity.User); ok {
			// 验证会话权限
			if err := h.validateConversationAccess(u.ID, req.ConversationID); err != nil {
				return response.Forbidden(c, "Access denied: "+err.Error())
			}

			// 1. 创建用户消息，使用预生成的对话轮次ID
			userMessage = &entity.ClientMessage{
				ConversationID:      conversationUUID,
				UserID:              u.ID,
				Role:                "user",
				Content:             req.Prompt,
				Status:              entity.ClientMessageStatusCompleted,
				ConversationRoundID: conversationRoundID,
			}

			if err := h.repos.GetClientMessage().CreateClientMessage(c.Request().Context(), userMessage); err != nil {
				// logger.StreamLog("Error", conversationUUID).Err(err).Msg("创建用户消息失败")
				log.Error().
					Str("conversation_id", req.ConversationID).
					Str("user_id", u.ID.String()).
					Msg("创建客户消息失败")
				return response.InternalServerError(c, "保存客户消息失败")
			}

			// 2. 创建assistant消息（初始状态为pending），使用相同的对话轮次ID
			assistantMessage = &entity.ClientMessage{
				ConversationID:      conversationUUID,
				UserID:              u.ID,
				Role:                "assistant",
				Content:             "", // 初始为空，处理完成后更新
				Status:              entity.ClientMessageStatusPending,
				ConversationRoundID: conversationRoundID,
			}

			if err := h.repos.GetClientMessage().CreateClientMessage(c.Request().Context(), assistantMessage); err != nil {
				log.Error().
					Str("conversation_id", req.ConversationID).
					Str("user_id", u.ID.String()).
					Msg("创建助手消息失败")
				return response.InternalServerError(c, "保存助手消息失败")
			}
		}
	}

	agent := h.agentHub.GetOrCreateAgent(conversationUUID)
	if agent == nil {
		// 返回统一的错误响应格式
		errorResp := sse.NewChatResponse(conversationUUID, sse.StatusError).
			WithError("AGENT_ERROR", "无法创建或获取代理", "系统内部错误，请稍后重试", true)
		c.Response().Header().Set(echo.HeaderContentType, "application/json")
		c.Response().WriteHeader(http.StatusInternalServerError)
		errorJSON, _ := errorResp.ToJSON()
		return c.String(http.StatusInternalServerError, errorJSON)
	}

	// 使用预生成的对话轮次ID，用于关联LLM消息
	streamResult, err := agent.ChatStream(c.Request().Context(), req.Prompt, conversationRoundID)
	if err != nil {
		if assistantMessage != nil {
			// 如果流式聊天创建失败，更新assistant消息状态为错误
			assistantMessage.Status = entity.ClientMessageStatusFailed
			h.repos.GetClientMessage().UpdateClientMessage(c.Request().Context(), assistantMessage)
		}

		log.Error().
			Str("conversation_id", req.ConversationID).
			Str("user_id", userMessage.UserID.String()).
			Err(err).
			Msg("流式聊天启动失败")

		return response.InternalServerError(c, "无法启动流式聊天")
	}

	// 确保在handler退出时取消AI处理（如果还没完成）
	defer streamResult.Cancel()

	// 设置SSE响应头
	sse.SetSSEHeaders(c)
	c.Response().WriteHeader(http.StatusOK)

	// 创建消息转换器和拦截器
	converter := sse.NewChatResponseConverter(&sse.DefaultInterceptor{})

	clientCtx := c.Request().Context()
	var userFacingContent strings.Builder // 收集用户回复内容
	var reasoningContent strings.Builder  // 收集AI推理过程
	var hasStreamedContent bool           // 标记是否已收集流式内容
	var hasStreamedReasoning bool         // 标记是否已收集推理内容
	var tokensUsed int                    // 累计token使用量
	var modelName string                  // 使用的模型名称

streamLoop:
	for {
		select {
		case <-clientCtx.Done():
			// 客户端断开连接，但AI处理继续
			log.Warn().
				Str("process", "Handler.Chat").
				Str("conversation_id", req.ConversationID).
				Msg("客户端断开连接，AI处理继续")
			return nil
		case output, ok := <-streamResult.MessageChan:
			if !ok {
				// 流式响应结束
				break streamLoop
			}

			// 收集AI回复内容、推理过程和元数据
			switch output.Status {
			case sse.StatusStreaming:
				// 收集流式内容的增量部分
				if output.DeltaContent != "" {
					userFacingContent.WriteString(output.DeltaContent)
					hasStreamedContent = true
				}
				// 收集推理内容的增量部分
				if output.DeltaReasoningContent != "" {
					reasoningContent.WriteString(output.DeltaReasoningContent)
					hasStreamedReasoning = true
				}
			case sse.StatusCompleted:
				// 如果没有流式内容，则使用完整内容
				if !hasStreamedContent && output.Content != "" {
					userFacingContent.WriteString(output.Content)
				}
				// 如果没有流式推理内容，则使用完整推理内容
				if !hasStreamedReasoning && output.ReasoningContent != "" {
					reasoningContent.WriteString(output.ReasoningContent)
				}
				// 收集完成时的元数据（如果可用）
				// 这些信息在后续更新assistant消息时会用到
			case sse.StatusToolCalling:
				// 工具调用状态，记录日志
				log.Info().
					Str("conversation_id", req.ConversationID).
					Str("status_message", output.StatusMessage).
					Msg("工具调用中")
			case sse.StatusToolCompleted:
				// 工具完成现在对用户可见，记录日志
				log.Info().
					Str("conversation_id", req.ConversationID).
					Str("status_message", output.StatusMessage).
					Msg("工具调用完成")
			case sse.StatusError:
				// 错误状态记录错误信息
				log.Error().
					Str("conversation_id", req.ConversationID).
					Interface("error", output.Error).
					Msg("处理过程中出现错误")
			}

			// 现在收集ReasoningContent，让用户看到完整的AI思考过程

			// 通过转换器和拦截器处理消息
			streamEvent := converter.Convert(clientCtx, output)
			if err := sse.SendSSE(c.Response(), streamEvent); err != nil {
				log.Error().
					Str("conversation_id", req.ConversationID).
					Str("component", "handler").
					Err(err).
					Msg("Error sending SSE event")
				return err
			}
		}
	}

	log.Info().
		Str("conversation_id", req.ConversationID).
		Msg("流式响应完成")

	// 更新assistant消息状态
	if assistantMessage != nil {
		// 使用收集的AI回复内容
		userReply := userFacingContent.String()
		if userReply == "" {
			userReply = "AI处理完成，但无文本回复"
		}

		// 使用收集的推理内容
		reasoningReply := reasoningContent.String()

		// 计算处理时间
		processingTime := time.Since(time.Unix(assistantMessage.CreatedAt.Unix(), 0)).Milliseconds()

		// 更新assistant消息为完成状态，包含推理内容
		assistantMessage.Content = userReply
		assistantMessage.ReasoningContent = reasoningReply
		assistantMessage.SetCompleted(processingTime, tokensUsed, modelName)

		if err := h.repos.GetClientMessage().UpdateClientMessage(c.Request().Context(), assistantMessage); err != nil {
			log.Error().
				Str("conversation_id", req.ConversationID).
				Str("assistant_message_id", assistantMessage.ID.String()).
				Err(err).
				Msg("Failed to update assistant message")
		}

		log.Info().
			Str("conversation_id", req.ConversationID).
			Int("content_length", len(userReply)).
			Int("reasoning_length", len(reasoningReply)).
			Int64("processing_time_ms", processingTime).
			Int("tokens_used", tokensUsed).
			Str("model", modelName).
			Msg("更新助手消息成功")
	}

	// 发送结束信号
	if err := sse.SendSSEEnd(c.Response()); err != nil {
		log.Error().
			Str("conversation_id", req.ConversationID).
			Err(err).
			Msg("Error sending end signal")
	}

	return nil
}

// GetConversationHistory 获取完整的对话历史
func (h *UserHandler) GetConversationHistory(c echo.Context) error {
	var params GetConversationHistoryRequest
	if err := c.Bind(&params); err != nil {
		return echo.NewHTTPError(http.StatusBadRequest, "Invalid request format")
	}

	if err := h.validator.Struct(&params); err != nil {
		return echo.NewHTTPError(http.StatusBadRequest, "Validation failed: "+err.Error())
	}

	conversationID := params.ConversationID

	// 解析 conversationID 为 UUID
	conversationUUID, err := uuid.Parse(conversationID)
	if err != nil {
		return echo.NewHTTPError(http.StatusBadRequest, "Invalid conversation ID format")
	}

	// 获取或创建agent
	agent := h.agentHub.GetOrCreateAgent(conversationUUID)

	// 获取完整对话历史
	messages, err := agent.GetConversationHistory()
	if err != nil {
		log.Error().
			Str("conversation_id", conversationID).
			Err(err).
			Msg("Error getting conversation history")
		return response.InternalServerError(c, "Failed to get conversation history")
	}

	// 构造响应格式
	resp := GetConversationHistoryResponse{
		ConversationID: conversationID,
		Messages:       messages,
		MessageCount:   len(messages),
		Timestamp:      time.Now().UnixMilli(),
	}

	return response.Success(c, resp)
}

// GetLatestResponse 获取最新的AI回复
func (h *UserHandler) GetLatestResponse(c echo.Context) error {
	var params GetLatestResponseRequest
	if err := c.Bind(&params); err != nil {
		return echo.NewHTTPError(http.StatusBadRequest, "Invalid request format")
	}

	if err := h.validator.Struct(&params); err != nil {
		return echo.NewHTTPError(http.StatusBadRequest, "Validation failed: "+err.Error())
	}

	conversationID := params.ConversationID

	// 解析 conversationID 为 UUID
	conversationUUID, err := uuid.Parse(conversationID)
	if err != nil {
		return echo.NewHTTPError(http.StatusBadRequest, "Invalid conversation ID format")
	}

	// 获取或创建agent
	agent := h.agentHub.GetOrCreateAgent(conversationUUID)

	// 获取最新的助手回复
	message, err := agent.GetLatestAssistantMessage()
	if err != nil {
		log.Error().
			Str("conversation_id", conversationID).
			Err(err).
			Msg("获取最新助手消息失败")
		return response.NotFound(c, "No assistant message found")
	}

	// 构造响应格式
	resp := GetLatestResponseResponse{
		ConversationID: conversationID,
		Message:        message,
		Timestamp:      time.Now().UnixMilli(),
	}

	return response.Success(c, resp)
}
